/* * Author: Chris Seguin * * This software has been developed under the copyleft * rules of the GNU General Public License. Please * consult the GNU General Public License for more * details about use and distribution of this software. */ package org.acm.seguin.summary; import org.acm.seguin.parser.Node; import org.acm.seguin.parser.ast.ASTAllocationExpression; import org.acm.seguin.parser.ast.ASTArguments; import org.acm.seguin.parser.ast.ASTBlock; import org.acm.seguin.parser.ast.ASTBlockStatement; import org.acm.seguin.parser.ast.ASTClassBody; import org.acm.seguin.parser.ast.ASTClassDeclaration; import org.acm.seguin.parser.ast.ASTConstructorDeclaration; import org.acm.seguin.parser.ast.ASTExplicitConstructorInvocation; import org.acm.seguin.parser.ast.ASTFieldDeclaration; import org.acm.seguin.parser.ast.ASTFormalParameter; import org.acm.seguin.parser.ast.ASTFormalParameters; import org.acm.seguin.parser.ast.ASTImportDeclaration; import org.acm.seguin.parser.ast.ASTInitializer; import org.acm.seguin.parser.ast.ASTInterfaceBody; import org.acm.seguin.parser.ast.ASTInterfaceDeclaration; import org.acm.seguin.parser.ast.ASTLocalVariableDeclaration; import org.acm.seguin.parser.ast.ASTMethodDeclaration; import org.acm.seguin.parser.ast.ASTMethodDeclarator; import org.acm.seguin.parser.ast.ASTName; import org.acm.seguin.parser.ast.ASTNameList; import org.acm.seguin.parser.ast.ASTNestedClassDeclaration; import org.acm.seguin.parser.ast.ASTNestedInterfaceDeclaration; import org.acm.seguin.parser.ast.ASTPackageDeclaration; import org.acm.seguin.parser.ast.ASTPrimaryExpression; import org.acm.seguin.parser.ast.ASTPrimaryPrefix; import org.acm.seguin.parser.ast.ASTPrimarySuffix; import org.acm.seguin.parser.ast.ASTPrimitiveType; import org.acm.seguin.parser.ast.ASTResultType; import org.acm.seguin.parser.ast.ASTStatement; import org.acm.seguin.parser.ast.ASTSwitchStatement; import org.acm.seguin.parser.ast.ASTType; import org.acm.seguin.parser.ast.ASTTypeDeclaration; import org.acm.seguin.parser.ast.ASTUnmodifiedClassDeclaration; import org.acm.seguin.parser.ast.ASTUnmodifiedInterfaceDeclaration; import org.acm.seguin.parser.ast.ASTVariableDeclaratorId; import org.acm.seguin.parser.ast.SimpleNode; /** * This object visits an abstract syntax tree with the purpose of gathering * summary information. * *@author Chris Seguin *@created May 30, 1999 */ public class SummaryLoadVisitor extends LineCountVisitor { private int anonCount = 1; /** * Visits a package declaration * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTPackageDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; // Get the name ASTName name = (ASTName) node.jjtGetChild(0); // Lookup the summary PackageSummary packageSummary = PackageSummary.getPackageSummary(name.getName()); // Create the file summary if (state.getCode() == SummaryLoaderState.INITIALIZE) { state.startSummary(new FileSummary(packageSummary, state.getFile())); state.setCode(SummaryLoaderState.LOAD_FILE); } return super.visit(node, data); } /** * Visits an import statement * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTImportDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; // Get the current file summary - add the import FileSummary current = (FileSummary) state.getCurrentSummary(); ImportSummary importSummary = new ImportSummary(current, node); current.add(importSummary); int start = getLineCount() + 1; // Done Object obj = super.visit(node, data); int end = getLineCount(); importSummary.setStartLine(start); importSummary.setEndLine(end); return obj; } /** * Visits a type declaration * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTTypeDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; // Get the current file summary FileSummary current = (FileSummary) state.getCurrentSummary(); // Create Type Summary TypeSummary next = new TypeSummary(current, node); current.add(next); // Set the next type summary as the current summary state.startSummary(next); int oldCode = state.getCode(); state.setCode(SummaryLoaderState.LOAD_TYPE); // Traverse Children super.visit(node, data); // Back to loading the file state.finishSummary(); state.setCode(oldCode); int end = getLineCount(); next.setStartLine(start); next.setEndLine(end); // Done return data; } /** * Visits a class declaration * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTClassDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; // Get the current type summary TypeSummary current = (TypeSummary) state.getCurrentSummary(); // Save the modifiers current.setModifiers(node.getModifiers()); // Traverse the children return super.visit(node, data); } /** * Visits a class declaration * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTUnmodifiedClassDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); // Get the current type summary Summary currentSummary = state.getCurrentSummary(); TypeSummary current; if (currentSummary instanceof TypeSummary) { current = (TypeSummary) currentSummary; } else { // Create Type Summary current = new TypeSummary(currentSummary, node); ((MethodSummary) currentSummary).addDependency(current); state.startSummary(current); } // Remember the name current.setName(node.getName().intern()); // Iterate through the children // Add the class body state.setCode(SummaryLoaderState.LOAD_TYPE); super.visit(node, data); state.setCode(code); // This is a class current.setInterface(false); if (currentSummary instanceof TypeSummary) { } else { state.finishSummary(); } return data; } /** * Visit the items in the class body * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTClassBody node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int oldCode = state.getCode(); state.setCode(SummaryLoaderState.LOAD_CLASSBODY); super.visit(node, data); state.setCode(oldCode); return data; } /** * Visit a class that is nested in another class * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTNestedClassDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); // Get the current type summary Summary current = state.getCurrentSummary(); TypeSummary nested = new TypeSummary(current, node); // Add it in if (current instanceof TypeSummary) { ((TypeSummary) current).add(nested); } else { ((MethodSummary) current).addDependency(nested); } // Continue deeper state.startSummary(nested); state.setCode(SummaryLoaderState.LOAD_TYPE); // Save the modifiers nested.setModifiers(node.getModifiers()); // Traverse the children super.visit(node, data); int end = getLineCount(); nested.setStartLine(start); nested.setEndLine(end); // Finish the summary state.finishSummary(); state.setCode(code); // Return something return data; } /** * Visit an interface declaration * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTInterfaceDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; // Get the current type summary TypeSummary current = (TypeSummary) state.getCurrentSummary(); // Save the modifiers current.setModifiers(node.getModifiers()); // Traverse the children return super.visit(node, data); } /** * Visit an interface that is nested in a class * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTNestedInterfaceDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); // Get the current type summary Summary current = state.getCurrentSummary(); // Create the new nested type summary TypeSummary nested = new TypeSummary(current, node); // Add it in if (current instanceof TypeSummary) { ((TypeSummary) current).add(nested); } else { ((MethodSummary) current).addDependency(nested); } // Continue deeper state.startSummary(nested); state.setCode(SummaryLoaderState.LOAD_TYPE); // Save the modifiers nested.setModifiers(node.getModifiers()); // Traverse the children super.visit(node, data); int end = getLineCount(); nested.setStartLine(start); nested.setEndLine(end); // Finish the summary state.finishSummary(); state.setCode(code); // Return something return data; } /** * Visit an interface * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTUnmodifiedInterfaceDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); // Get the current type summary Summary currentSummary = state.getCurrentSummary(); TypeSummary current; if (currentSummary instanceof TypeSummary) { current = (TypeSummary) currentSummary; } else { // Create Type Summary current = new TypeSummary(currentSummary, node); ((MethodSummary) currentSummary).addDependency(current); state.startSummary(current); } // Remember the name current.setName(node.getName().intern()); // Iterate through the children of the interface state.setCode(SummaryLoaderState.LOAD_TYPE); super.visit(node, data); state.setCode(code); // This is an interface current.setInterface(true); if (currentSummary instanceof TypeSummary) { } else { state.finishSummary(); } // Done return data; } /** * Visit the body of an interface * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTInterfaceBody node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int oldCode = state.getCode(); state.setCode(SummaryLoaderState.LOAD_CLASSBODY); super.visit(node, data); state.setCode(oldCode); return data; } /** * Visit a field declaration * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTFieldDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); state.setCode(SummaryLoaderState.IGNORE); countFieldStart(node, data); state.setCode(code); // Get the current type summary TypeSummary current = (TypeSummary) state.getCurrentSummary(); // Local Variables FieldSummary result = null; int last = node.jjtGetNumChildren(); ASTType type = (ASTType) node.jjtGetChild(0); // Create a summary for each field for (int ndx = 1; ndx < last; ndx++) { Node next = node.jjtGetChild(ndx); result = new FieldSummary(current, type, (ASTVariableDeclaratorId) next.jjtGetChild(0)); // Count anything on the declarator state.setCode(SummaryLoaderState.IGNORE); next.jjtGetChild(0).jjtAccept(this, data); state.setCode(code); // Continue setting up the field summary result.setModifiers(node.getModifiers()); result.setStartLine(start); // Load the initializer if (next.jjtGetNumChildren() > 1) { loadInitializer(current, state, (SimpleNode) next.jjtGetChild(1), node.getModifiers().isStatic()); } // Finish setting variables for the field summary countLines(node.getSpecial("comma" + (ndx - 2))); result.setEndLine(getLineCount()); current.add(result); } countLines(node.getSpecial("semicolon")); if (result != null) { result.setEndLine(getLineCount()); } return data; } /** * Visits a method * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTMethodDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; countMethodHeader(node, data); int declStart = getLineCount(); int code = state.getCode(); if (code == SummaryLoaderState.LOAD_CLASSBODY) { ASTMethodDeclarator decl = (ASTMethodDeclarator) node.jjtGetChild(1); // Get the current type summary TypeSummary current = (TypeSummary) state.getCurrentSummary(); MethodSummary methodSummary = new MethodSummary(current); state.startSummary(methodSummary); current.add(methodSummary); // Load the method summary // Remember the modifiers methodSummary.setModifiers(node.getModifiers()); // Load the method names methodSummary.setName(decl.getName()); // Load the return type loadMethodReturn(node, methodSummary, decl.getArrayCount()); // Load the parameters loadMethodParams(decl, state); // Load the exceptions loadMethodExceptions(node, state, 2); // Initialize the dependency list loadMethodBody(node, state); // Done state.setCode(SummaryLoaderState.LOAD_CLASSBODY); state.finishSummary(); int end = getLineCount(); methodSummary.setStartLine(start); methodSummary.setDeclarationLine(declStart); methodSummary.setEndLine(end); return data; } else { System.out.println("Encountered a method in state: " + code); return data; } } /** * Visit a formal parameter * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTFormalParameter node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); if (code == SummaryLoaderState.LOAD_PARAMETERS) { // Local Variables MethodSummary methodSummary = (MethodSummary) state.getCurrentSummary(); // For each variable create a summary methodSummary.add(new ParameterSummary(methodSummary, (ASTType) node.jjtGetChild(0), (ASTVariableDeclaratorId) node.jjtGetChild(1))); // Continue with the state return state; } else { // Get the parent MethodSummary parent = (MethodSummary) state.getCurrentSummary(); // Add the dependency parent.addDependency(new ParameterSummary(parent, (ASTType) node.jjtGetChild(0), (ASTVariableDeclaratorId) node.jjtGetChild(1))); // Return something return data; } } /** * Visit a constructor * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTConstructorDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int code = state.getCode(); if (code == SummaryLoaderState.LOAD_CLASSBODY) { int start = getLineCount() + 1; countConstructorHeader(node); int declStart = getLineCount(); // Get the current type summary TypeSummary current = (TypeSummary) state.getCurrentSummary(); MethodSummary methodSummary = new MethodSummary(current); current.add(methodSummary); state.startSummary(methodSummary); // Load the constructor // Remember the modifiers methodSummary.setModifiers(node.getModifiers()); // Load the method names methodSummary.setName(node.getName()); // Load the parameters loadMethodParams(node, state); // Load the exceptions loadMethodExceptions(node, state, 1); // Initialize the dependency list methodSummary.beginBlock(); state.setCode(SummaryLoaderState.LOAD_METHODBODY); int last = node.jjtGetNumChildren(); for (int ndx = 1; ndx < last; ndx++) { SimpleNode body = (SimpleNode) node.jjtGetChild(ndx); if (body instanceof ASTExplicitConstructorInvocation) { body.jjtAccept(this, data); } else if (body instanceof ASTBlockStatement) { body.jjtAccept(this, data); } } methodSummary.endBlock(); // Done state.setCode(SummaryLoaderState.LOAD_CLASSBODY); state.finishSummary(); countLines(node.getSpecial("end")); int end = getLineCount(); methodSummary.setStartLine(start); methodSummary.setDeclarationLine(declStart); methodSummary.setEndLine(end); return data; } else { System.out.println("Encountered a constructor in state: " + code); return data; } } /** * Visit an initializer * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTInitializer node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; int code = state.getCode(); if (code == SummaryLoaderState.LOAD_CLASSBODY) { // Get the current type summary TypeSummary current = (TypeSummary) state.getCurrentSummary(); int last = node.jjtGetNumChildren(); SimpleNode body = (SimpleNode) node.jjtGetChild(last - 1); if (body instanceof ASTBlock) { loadInitializer(current, state, body, node.isUsingStatic()); } return data; } else { System.out.println("Encountered a method in state: " + code); return data; } } /** * Visit a type * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTType node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } MethodSummary parent = (MethodSummary) state.getCurrentSummary(); // Add the dependency parent.addDependency(TypeDeclSummary.getTypeDeclSummary(parent, node)); // Return the data return super.visit(node, data); } /** * Visit a return type * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTResultType node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; MethodSummary parent = (MethodSummary) state.getCurrentSummary(); // Add the dependency parent.addDependency(TypeDeclSummary.getTypeDeclSummary(parent, node)); // Return the data return data; } /** * Visit a name * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTName node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int code = state.getCode(); // Get the current type summary if (code == SummaryLoaderState.LOAD_TYPE) { TypeSummary current = (TypeSummary) state.getCurrentSummary(); current.setParentClass(new TypeDeclSummary(current, node)); } return super.visit(node, data); } /** * Visit a list of names * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTNameList node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int code = state.getCode(); // Get the current type summary if (code == SummaryLoaderState.LOAD_TYPE) { TypeSummary current = (TypeSummary) state.getCurrentSummary(); // Local Variables int last = node.jjtGetNumChildren(); // For each interface it implements create a summary state.setCode(SummaryLoaderState.IGNORE); for (int ndx = 0; ndx < last; ndx++) { countLines(node.getSpecial("comma." + (ndx - 1))); ASTName next = (ASTName) node.jjtGetChild(ndx); current.add(new TypeDeclSummary(current, next)); next.jjtAccept(this, data); } state.setCode(code); return data; } else if (code == SummaryLoaderState.LOAD_EXCEPTIONS) { // Local Variables int last = node.jjtGetNumChildren(); MethodSummary methodSummary = (MethodSummary) state.getCurrentSummary(); // For each variable create a summary state.setCode(SummaryLoaderState.IGNORE); for (int ndx = 0; ndx < last; ndx++) { countLines(node.getSpecial("comma." + (ndx - 1))); ASTName next = (ASTName) node.jjtGetChild(ndx); methodSummary.add(new TypeDeclSummary(methodSummary, next)); next.jjtAccept(this, data); } state.setCode(code); // Return something return data; } else { return super.visit(node, data); } } /** * Visit an expression * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTPrimaryExpression node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; // Local Variables ASTName name; // Check out the prefix ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) node.jjtGetChild(0); if (!prefix.hasAnyChildren()) { // Count the lines countLines(node.getSpecial("this")); countLines(node.getSpecial("id")); // It is entirely controlled by the name of the node String prefixName = prefix.getName(); // Create the name name = new ASTName(0); // Check out the name if (prefixName.equals("this")) { name.addNamePart(prefixName); } else { name.addNamePart("super"); name.addNamePart(prefixName.substring(7, prefixName.length())); } } else if (prefix.jjtGetChild(0) instanceof ASTName) { // Count the items in the name int code = state.getCode(); state.setCode(SummaryLoaderState.IGNORE); super.visit(prefix, data); state.setCode(code); // Remember the name name = (ASTName) prefix.jjtGetChild(0); } else { // Our work is done here return super.visit(node, data); } // Get the parent MethodSummary parent = (MethodSummary) state.getCurrentSummary(); // Check out the suffix boolean isMessageSend = false; int suffixCount = node.jjtGetNumChildren(); boolean sentLast = false; if (suffixCount > 1) { for (int ndx = 1; ndx < suffixCount; ndx++) { ASTPrimarySuffix suffix = (ASTPrimarySuffix) node.jjtGetChild(ndx); if (!suffix.hasAnyChildren()) { // Count the lines countLines(node.getSpecial("dot")); countLines(node.getSpecial("id")); name = new ASTName(0); name.addNamePart(suffix.getName()); sentLast = false; } else if (suffix.jjtGetChild(0) instanceof ASTArguments) { addAccess(parent, name, true); sentLast = true; super.visit((SimpleNode) suffix.jjtGetChild(0), data); } else if (!sentLast) { addAccess(parent, name, false); sentLast = true; // Count the lines countLines(node.getSpecial("[")); countLines(node.getSpecial("]")); countLines(node.getSpecial("dot")); countLines(node.getSpecial("id")); super.visit((SimpleNode) suffix.jjtGetChild(0), data); } } } // Get the parent if (!sentLast) { addAccess(parent, name, false); } // Return some value return data; } /** * Visit an allocation * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTAllocationExpression node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; MethodSummary parent = (MethodSummary) state.getCurrentSummary(); // Add the dependency Node child = node.jjtGetChild(0); TypeDeclSummary parentClass = null; if (child instanceof ASTName) { parentClass = new TypeDeclSummary(parent, (ASTName) child); } else if (child instanceof ASTPrimitiveType) { parentClass = new TypeDeclSummary(parent, (ASTPrimitiveType) child); } parent.addDependency(parentClass); // Count the lines in the type and before countLines(node.getSpecial("id")); int code = state.getCode(); state.setCode(SummaryLoaderState.IGNORE); child.jjtAccept(this, data); state.setCode(code); int last = node.jjtGetNumChildren(); for (int ndx = 1; ndx < last; ndx++) { Node next = node.jjtGetChild(ndx); if (next instanceof ASTClassBody) { // Create Type Summary TypeSummary typeSummary = new TypeSummary(parent, null); typeSummary.setName("Anonymous" + anonCount); anonCount++; typeSummary.setParentClass(parentClass); parent.addDependency(typeSummary); // Set the next type summary as the current summary state.startSummary(typeSummary); int oldCode = state.getCode(); state.setCode(SummaryLoaderState.LOAD_TYPE); // Traverse Children next.jjtAccept(this, data); // Back to loading the file state.finishSummary(); state.setCode(oldCode); } else { ((SimpleNode) next).jjtAccept(this, data); } } int end = getLineCount(); parentClass.setStartLine(start); parentClass.setEndLine(end); // Return the data return data; } /** * Visit a statement * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTStatement node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } Node child = node.jjtGetChild(0); if (child instanceof ASTBlock) { // Don't count blocks as statements } else { MethodSummary parent = (MethodSummary) state.getCurrentSummary(); parent.incrStatementCount(); } return super.visit(node, data); } /** * Explicit constructor invocation gets one statement count * *@param node Description of Parameter *@param data Description of Parameter *@return Description of the Returned Value */ public Object visit(ASTExplicitConstructorInvocation node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } MethodSummary parent = (MethodSummary) state.getCurrentSummary(); parent.incrStatementCount(); return super.visit(node, data); } /** * Visit the local variables * *@param node the node we are visiting *@param data the state we are in *@return nothing of interest */ public Object visit(ASTLocalVariableDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } int start = getLineCount() + 1; countLocalVariable(node, data); int end = getLineCount(); MethodSummary parent = (MethodSummary) state.getCurrentSummary(); parent.incrStatementCount(); // Get the field summaries LocalVariableSummary[] result = LocalVariableSummary.createNew(parent, node); // Add the dependencies into the method int last = result.length; for (int ndx = 0; ndx < last; ndx++) { parent.addDependency(result[ndx]); result[ndx].setStartLine(start); result[ndx].setEndLine(end); } // Return some result return data; } /** * Description of the Method * *@param node Description of Parameter *@param data Description of Parameter */ protected void forInit(ASTLocalVariableDeclaration node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { super.visit(node, data); return; } int start = getLineCount() + 1; countLocalVariable(node, data); int end = getLineCount(); MethodSummary parent = (MethodSummary) state.getCurrentSummary(); // Get the field summaries LocalVariableSummary[] result = LocalVariableSummary.createNew(parent, node); // Add the dependencies into the method int last = result.length; for (int ndx = 0; ndx < last; ndx++) { parent.addDependency(result[ndx]); result[ndx].setStartLine(start); result[ndx].setEndLine(end); } } /** * Visits a block in the parse tree. This code counts the block depth * associated with a method. Deeply nested blocks in a method is a sign of * poor design. * *@param node the block node *@param data the information that is used to traverse the tree *@return data is returned */ public Object visit(ASTBlock node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } // Get the current file summary Summary current = state.getCurrentSummary(); if (current instanceof MethodSummary) { ((MethodSummary) current).beginBlock(); } Object result = super.visit(node, data); if (current instanceof MethodSummary) { ((MethodSummary) current).endBlock(); } return result; } /** * A switch statement counts as a block, even though it * does not use the block parse token. * *@param node the switch node in the parse tree *@param data the data used to visit this parse tree *@return the data */ public Object visit(ASTSwitchStatement node, Object data) { // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; if (state.getCode() == SummaryLoaderState.IGNORE) { return super.visit(node, data); } // Get the current file summary Summary current = state.getCurrentSummary(); if (current instanceof MethodSummary) { ((MethodSummary) current).beginBlock(); } Object result = super.visit(node, data); if (current instanceof MethodSummary) { ((MethodSummary) current).endBlock(); } return result; } /** * Adds an access to the method * *@param parent the parent *@param name the name *@param isMessageSend is this a message send */ protected void addAccess(MethodSummary parent, ASTName name, boolean isMessageSend) { // Record the access if (isMessageSend) { // Add the dependency parent.addDependency(new MessageSendSummary(parent, (ASTName) name)); } else { // Add the dependency parent.addDependency(new FieldAccessSummary(parent, (ASTName) name)); } } /** * Description of the Method * *@param current Description of Parameter *@param state Description of Parameter *@param body Description of Parameter *@param isStatic Description of Parameter */ void loadInitializer(TypeSummary current, SummaryLoaderState state, SimpleNode body, boolean isStatic) { MethodSummary methodSummary = current.getInitializer(isStatic); state.startSummary(methodSummary); // Load the method summary's dependency list int oldCode = state.getCode(); state.setCode(SummaryLoaderState.LOAD_METHODBODY); body.jjtAccept(this, state); // Done state.setCode(oldCode); state.finishSummary(); } /** * Counts the lines associated with the field declaration and the associated * type * *@param node the field declaration *@param data the data for the visitor */ private void countFieldStart(ASTFieldDeclaration node, Object data) { // Print any tokens countLines(node.getSpecial("static")); countLines(node.getSpecial("transient")); countLines(node.getSpecial("volatile")); countLines(node.getSpecial("final")); countLines(node.getSpecial("public")); countLines(node.getSpecial("protected")); countLines(node.getSpecial("private")); // Handle the first two children (which are required) Node next = node.jjtGetChild(0); next.jjtAccept(this, data); } /** * Description of the Method * *@param node Description of Parameter *@param data Description of Parameter */ private void countMethodHeader(ASTMethodDeclaration node, Object data) { countLines(node.getSpecial("public")); countLines(node.getSpecial("protected")); countLines(node.getSpecial("private")); countLines(node.getSpecial("static")); countLines(node.getSpecial("abstract")); countLines(node.getSpecial("final")); countLines(node.getSpecial("native")); countLines(node.getSpecial("synchronized")); countLines(getInitialToken((ASTResultType) node.jjtGetChild(0))); countLines(node.getSpecial("throws")); countLines(node.getSpecial("semicolon")); } /** * Description of the Method * *@param node Description of Parameter */ private void countConstructorHeader(ASTConstructorDeclaration node) { countLines(node.getSpecial("public")); countLines(node.getSpecial("protected")); countLines(node.getSpecial("private")); countLines(node.getSpecial("id")); countLines(node.getSpecial("throws")); countLines(node.getSpecial("begin")); } /** * Description of the Method * *@param decl Description of Parameter *@param state Description of Parameter */ private void loadMethodParams(SimpleNode decl, SummaryLoaderState state) { Node child = decl.jjtGetChild(0); if (!(child instanceof ASTFormalParameters)) { System.out.println("ERROR! Not formal parameters"); return; } state.setCode(SummaryLoaderState.LOAD_PARAMETERS); child.jjtAccept(this, state); } /** * Description of the Method * *@param node Description of Parameter *@param methodSummary Description of Parameter *@param count Description of Parameter */ private void loadMethodReturn(ASTMethodDeclaration node, MethodSummary methodSummary, int count) { TypeDeclSummary returnType = TypeDeclSummary.getTypeDeclSummary(methodSummary, (ASTResultType) node.jjtGetChild(0)); returnType.setArrayCount(returnType.getArrayCount() + count); methodSummary.setReturnType(returnType); } /** * Description of the Method * *@param node Description of Parameter *@param state Description of Parameter *@param index Description of Parameter */ private void loadMethodExceptions(SimpleNode node, SummaryLoaderState state, int index) { if (node.jjtGetNumChildren() > index) { Node child = node.jjtGetChild(index); if (child instanceof ASTNameList) { state.setCode(SummaryLoaderState.LOAD_EXCEPTIONS); child.jjtAccept(this, state); } } } /** * Description of the Method * *@param node Description of Parameter *@param state Description of Parameter */ private void loadMethodBody(ASTMethodDeclaration node, SummaryLoaderState state) { state.setCode(SummaryLoaderState.LOAD_METHODBODY); int last = node.jjtGetNumChildren(); SimpleNode body = (SimpleNode) node.jjtGetChild(last - 1); if (body instanceof ASTBlock) { body.jjtAccept(this, state); } } private void countLocalVariable(ASTLocalVariableDeclaration node, Object data) { // Traverse the children int last = node.jjtGetNumChildren(); // Print the final token if (node.isUsingFinal()) { countLines(node.getSpecial("final")); } // Convert the data into the correct form SummaryLoaderState state = (SummaryLoaderState) data; // The first child is special - it is the type int code = state.getCode(); state.setCode(SummaryLoaderState.IGNORE); node.jjtGetChild(0).jjtAccept(this, data); state.setCode(code); // Traverse the rest of the children for (int ndx = 1; ndx < last; ndx++) { countLines(node.getSpecial("comma." + (ndx - 1))); // Visit the child node.jjtGetChild(ndx).jjtAccept(this, data); } } }